package com.xiannimei.util;

import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;

import net.coobird.thumbnailator.Thumbnails;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;

import com.xiannimei.BusinessException;
import com.xiannimei.Constants;

public class AvatarUtil {
	protected static final Logger log = LoggerFactory.getLogger(AvatarUtil.class);

	public static char CHARSMALL = 'S';
	public static char CHARLARGE = 'L';
	public static char CHARUPLOAD = 'U';

	private static long K = 1024L;
	private static long M = 1024 * K;
	private static long maxFileSize = 5 * M;
	private static String targetSuffix = "png";
	private static String acceptableSuffix = ".jpg.gif.png.JPG.GIF.PNG";

	private static int E_FILETOOLARGE = 600101;
	private static int E_FILENOTACEPTBLE = 600102;
	private static int E_GENERICTHUMB = 600103;
	private static int E_GETAVATAR = 600104;
	private static int E_READUPLOAD = 600105;
	private static int E_SCALEAVATAR = 600106;

	private static Map<Character, Dimension> sizeMap;

	static {
		sizeMap = new HashMap<Character, Dimension>();
		sizeMap.put(CHARLARGE, new Dimension(180, 180));
		sizeMap.put(CHARSMALL, new Dimension(70, 70));
	}

	/**
	 * 上传原始头像
	 */
	public static void uploadTempAvatar(MultipartFile fileUpload, Long memberId) {
		if (isAcceptable(fileUpload.getOriginalFilename())) {
			if (fileUpload.getSize() <= maxFileSize && fileUpload.getSize() > 0) {
				File file = new File(getMemberAvatarPath(memberId, CHARUPLOAD));
				file.getParentFile().mkdirs();
				try {
					FileCopyUtils.copy(fileUpload.getBytes(), file);
				} catch (IOException e) {
					throw new BusinessException(E_READUPLOAD);
				}
			} else
				throw new BusinessException(E_FILETOOLARGE, maxFileSize / M, 'M');
		} else
			throw new BusinessException(E_FILENOTACEPTBLE);
	}

	/**
	 * 剪裁本地头像
	 */
	public static void scaleLocalAvatar(Long memberId, Rectangle rectangle, Dimension dimension) {
		try {
			File file = new File(getMemberAvatarPath(memberId, CHARUPLOAD));
			BufferedImage bi = ImageIO.read(file);
			double prop = (double) bi.getWidth() / (double) dimension.width;
			Rectangle rect = new Rectangle((int) (rectangle.x * prop), (int) (rectangle.y * prop),
					(int) (rectangle.width * prop), (int) (rectangle.height * prop));
			Thumbnails.of(bi).forceSize(rect.width, rect.height).sourceRegion(rect).toFile(file);
			createLocalAvatarFromImage(ImageIO.read(file), memberId);
		} catch (IOException e) {
			throw new BusinessException(E_SCALEAVATAR);
		}
	}

	/**
	 * 获取远程头像生成本地文件并返回文件相对路径
	 */
	public static void createLocalAvatarFromRemote(String uploadPath, Long memberId) {
		try {
			createLocalAvatarFromImage(ImageIO.read(new URL(uploadPath).openStream()), memberId);
		} catch (IOException e) {
			throw new BusinessException(E_GETAVATAR);
		}
	}

	/**
	 * 根据输入流生成各大小缩略图
	 */
	private static void createLocalAvatarFromImage(BufferedImage bi, Long memberId) {
		try {
			File file = new File(getMemberAvatarPath(memberId, CHARUPLOAD));
			file.getParentFile().mkdirs();
			for (Map.Entry<Character, Dimension> entry : sizeMap.entrySet())
				Thumbnails.of(bi).forceSize(entry.getValue().width, entry.getValue().height)
						.toFile(getMemberAvatarPath(memberId, entry.getKey()));
		} catch (IOException e) {
			throw new BusinessException(E_GENERICTHUMB);
		}
	}

	/**
	 * 获取用户头像硬盘地址
	 */
	public static String getMemberAvatarPath(Long memberId, char size) {
		return Constants.getConfig("localImgRoot") + getMemberAvatarUrl(memberId, size);
	}

	/**
	 * 获取用户头像硬盘地址
	 */
	public static String getMemberAvatarUrl(Long memberId, char size) {
		return Constants.getConfig("avatarPath") + "/" + hash(memberId.toString(), 100) + "/" + memberId + size + "." + targetSuffix;
	}

	/**
	 * 判断该路径的文件是否可以接受
	 */
	private static boolean isAcceptable(String path) {
		return acceptableSuffix.indexOf(getSuffix(path).toLowerCase()) != -1;
	}

	/**
	 * 求hash值
	 */
	private static int hash(String key, int limits) {
		int hashCode = 0;
		int i = 0;
		int len = key.length();
		for (; i < len; i++) {
			hashCode = ((hashCode * 33) + key.codePointAt(i)) & 0x7fffffff;
		}
		return hashCode % limits;
	}

	/**
	 * 获取URL文件后缀
	 */
	private static String getSuffix(String url) {
		int endIndex = url.lastIndexOf('?');
		if (endIndex > 0)
			url = url.substring(0, endIndex);
		return url.substring(url.lastIndexOf('.') + 1);
	}

}
